package com.neusoft.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.neusoft.base.BaseServiceImpl;
import com.neusoft.config.Pagination;
import com.neusoft.mapper.*;
import com.neusoft.model.ItemSearch;
import com.neusoft.po.Package;
import com.neusoft.po.*;
import com.neusoft.service.ItemService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品服务实现
 *
 * @author Lucifer
 * @since 2021/5/16 8:06
 */
@Service
public class ItemServiceImpl extends BaseServiceImpl<Item> implements ItemService {


    @Resource
    private ItemMapper itemMapper;
    @Resource
    private CommentMapper commentMapper;
    @Resource
    private PackageMapper packageMapper;
    @Resource
    private OrderItemRelMapper orderItemRelMapper;
    @Resource
    private CarMapper carMapper;
    @Resource
    private OrderMapper orderMapper;

    @Override
    public BaseMapper<Item> getBaseDao() {
        return itemMapper;
    }

    @Override
    public List<Item> banner() {
        List<Integer> items = orderItemRelMapper.mostSold();
        if (items.size() < 5) {
            return itemMapper.supple(items, 5 - items.size());
        } else {
            return itemMapper.selectList(new QueryWrapper<Item>().in("id", items));
        }
    }

    @Override
    public Integer save(Item entity) {
        Integer id = entity.getId();
        if (null == id) {
            entity.setCreate_time(new Date());
            insert(entity);
            id = entity.getId();
        } else {
            Item oldItem = itemMapper.selectById(id);
            if (oldItem.getPrice().compareTo(entity.getPrice()) != 0) {
                new Thread(() -> refreshOrderPrice(entity.getId())).start();
            }
            entity.setUpdate_time(new Date());
            updateById(entity);
        }
        return id;
    }

    private void refreshOrderPrice(Integer id) {
        List<Integer> order_ids = orderMapper.selectNotSumbit(id);
        order_ids.forEach(order_id -> {
            List<Integer> item_ids = orderItemRelMapper.selectList(new QueryWrapper<OrderItemRel>()
                    .eq("order_id", order_id)).stream().map(OrderItemRel::getItem_id).collect(Collectors.toList());
            Price price = price(item_ids.toArray(new Integer[]{}));
            orderMapper.updatePrice(price.getReal_total(), order_id);
        });
    }

    @Override
    public List<Item> list(ItemSearch itemSearch) {
        return itemMapper.list(itemSearch);
    }

    @Override
    @Pagination
    public Object page(ItemSearch itemSearch) {
        return itemMapper.list(itemSearch);
    }

    @Override
    public Item getWithComments(Integer id) {
        List<Item> items = itemMapper.getWithComments(new Integer[]{id});
        if (!items.isEmpty()) {
            return items.get(0);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer delete(Integer[] ids) {
        for (Integer id : ids) {
            packageMapper.delete(new QueryWrapper<Package>().eq("item_id", id));
            orderItemRelMapper.delete(new QueryWrapper<OrderItemRel>().eq("item_id", id));
            carMapper.delete(new QueryWrapper<CarItemRel>().eq("item_id", id));
            commentMapper.delete(new QueryWrapper<Comment>().eq("item_id", id));
        }
        return ids.length;
    }

    @Override
    public Price price(Integer[] ids) {
        List<Item> items = itemMapper.getWithComments(ids);
        Map<Integer, List<Item>> fulllessMap = items.stream()
                .collect(Collectors.groupingBy(item -> null == item.getFullless_id() ? 0 : item.getFullless_id(),
                        Collectors.toList()));
        double o_total = 0;
        double bysale = 0;
        double byfullless = 0;
        double r_total = 0;
        for (Map.Entry<Integer, List<Item>> entry : fulllessMap.entrySet()) {
            Integer k = entry.getKey();
            List<Item> v = entry.getValue();
            double sale_sum = v.stream().mapToDouble(i -> null == i.getSale_price() ? i.getPrice() : i.getSale_price()).sum();
            double o_sum = v.stream().mapToDouble(Item::getPrice).sum();
            o_total += o_sum;
            bysale += (o_sum - sale_sum);
            if (k != 0) {
                Fullless fullless = v.get(0).getFullless();
                int full = fullless.getFull();
                if (sale_sum >= full) {
                    sale_sum = sale_sum - fullless.getLess();
                    byfullless += fullless.getLess();
                }
            }
            r_total += sale_sum;
        }
        return new Price(o_total, bysale, byfullless, r_total);
    }
}
